package com.aek.ebey.sys.service.impl;

import java.util.Date;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import com.aek.common.core.base.BaseServiceImpl;
import com.aek.common.core.exception.ExceptionFactory;
import com.aek.common.core.serurity.WebSecurityUtils;
import com.aek.common.core.serurity.model.AuthUser;
import com.aek.common.core.util.PinyinUtil;
import com.aek.ebey.sys.mapper.SysUserMapper;
import com.aek.ebey.sys.model.SysDept;
import com.aek.ebey.sys.model.SysRole;
import com.aek.ebey.sys.model.SysTenant;
import com.aek.ebey.sys.model.SysUser;
import com.aek.ebey.sys.model.query.UserQuery;
import com.aek.ebey.sys.service.SysDeptService;
import com.aek.ebey.sys.service.SysRoleService;
import com.aek.ebey.sys.service.SysTenantService;
import com.aek.ebey.sys.service.SysUserService;
import com.aek.ebey.sys.service.ribbon.AuthClientService;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.google.common.collect.Lists;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author aek
 * @since 2017-05-06
 */
@Service
public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser> implements SysUserService
{
    
    @Autowired
    private SysUserMapper userMapper;
    
    @Autowired
    private SysDeptService sysDeptService;
    
    @Autowired
    private SysTenantService sysTenantService;
    
    @Autowired
    private SysRoleService sysRoleService;
    
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    @Autowired
    private AuthClientService authClientService;
    
    @Override
    public SysUser initTenantAdminUser(SysTenant tenant, SysUser admin)
    {
        Date currTime = new Date();
        // 机构根部门
        SysDept rootDept = this.sysDeptService.findRootDeptByTenantId(tenant.getId());
        
        admin.setAdminFlag(false);
        admin.setTenantId(tenant.getId());
        admin.setTenantName(tenant.getName());
        admin.setDeptId(rootDept.getId());
        admin.setDeptName(rootDept.getName());
        admin.setCreateTime(currTime);
        admin.setUpdateTime(currTime);
        this.createTenantAdmin(admin);
        
        // 添加管理员id
        tenant.setAdminId(admin.getId());
        this.sysTenantService.updateById(tenant);
        // 机构管理员赋予角色
        SysRole role = this.sysRoleService.findAdminRoleByTenantId(tenant.getId());
        this.sysRoleService.addRoleToUser(role.getId(), tenant.getId(), admin.getId());
        return admin;
    }
    
    @Override
    public void createTenantAdmin(SysUser admin)
    {
        // 重复验证
        this.checkDuplicate(admin);
        admin.setPassword(this.encrypt(admin.getPassword()));
        
        this.insert(admin);
    }
    
    /**
     * 增加修改数据重复检查
     * 
     * @param user
     */
    private void checkDuplicate(SysUser user)
    {
        SysUser mobileUser = null;
        SysUser emailUser = null;
        
        if (StringUtils.isNotBlank(user.getMobile()))
        {
            mobileUser = this.findByMobile(user.getMobile());
        }
        if (StringUtils.isNotBlank(user.getEmail()))
        {
            emailUser = this.findByEmail(user.getEmail());
        }
        
        if (user.getId() == null)
        { // 添加
            if (mobileUser != null)
                throw ExceptionFactory.create("U_013");
            if (emailUser != null)
                throw ExceptionFactory.create("U_014");
        }
        else
        {
            // 修改除自身数据相同
            if (mobileUser != null && !user.getId().equals(mobileUser.getId()))
                throw ExceptionFactory.create("U_013");
            if (emailUser != null && !user.getId().equals(emailUser.getId()))
                throw ExceptionFactory.create("U_014");
        }
        if (user.getTenantId() != null)
        {
            Wrapper<SysTenant> wrapper = new EntityWrapper<SysTenant>();
            wrapper.eq("del_flag", false);
            wrapper.eq("enable", true);
            wrapper.eq("id", user.getTenantId());
            SysTenant sysTenant = this.sysTenantService.selectOne(wrapper);
            if (sysTenant == null)
            {
                throw ExceptionFactory.create("O_008");
            }
            user.setTenantName(sysTenant.getName());
        }
        
        // 判断部门存在
        if (user.getDeptId() != null)
        {
            Wrapper<SysDept> wrapper = new EntityWrapper<SysDept>();
            wrapper.eq("del_flag", false);
            wrapper.eq("enable", true);
            wrapper.eq("id", user.getDeptId());
            SysDept dept = this.sysDeptService.selectOne(wrapper);
            if (dept == null)
            {
                throw ExceptionFactory.create("D_009");
            }
            user.setDeptName(dept.getName());
            user.setParentDeptIds(dept.getParentIds());
        }
    }
    
    @Override
    public SysUser findByMobile(String mobile)
    {
        SysUser user = new SysUser();
        user.setMobile(mobile);
        return this.userMapper.selectOne(user);
    }
    
    public SysUser findByUserId(Long userId)
    {
        SysUser user = new SysUser();
        user.setId(userId);
        return this.userMapper.selectOne(user);
    }
    
    @Override
    public SysUser findByEmail(String Email)
    {
        SysUser user = new SysUser();
        user.setEmail(Email);
        return this.userMapper.selectOne(user);
    }
    
    @Override
    public String encrypt(String password)
    {
        return this.passwordEncoder.encode(password);
    }
    
    /**
     * 修改用户密码
     * 
     * @param userId
     *            用户id
     * @param password
     *            新密码
     * @return
     */
    @Override
    public boolean changePassword(Long userId, String password)
    {
        SysUser entity = new SysUser();
        entity.setId(userId);
        
        entity.setPassword(this.encrypt(password));
        entity.setUpdateTime(new Date());
        
        Wrapper<SysUser> wrapper = new EntityWrapper<SysUser>();
        wrapper.eq("id", userId);
        wrapper.eq("del_flag", false);
        boolean res = this.update(entity, wrapper);
        
        //管理员修改用户密码 用户需要重新登录
        AuthUser user = WebSecurityUtils.getCurrentUser();
        if (Long.valueOf(user.getId()) != userId)
        {
            SysUser operUser = findByUserId(userId);
            authClientService.removeUser(operUser.getMobile(), WebSecurityUtils.getCurrentToken());
        }
        return res;
    }
    
    @Override
    public boolean checkPassword(SysUser user, String inPwd)
    {
        if (user == null)
        {
            return false;
        }
        
        if (StringUtils.isBlank(user.getPassword()) || StringUtils.isBlank(inPwd))
        {
            return false;
        }
        // return StringUtils.equals(this.encrypt(inPwd, user.getRegistId()),
        // user.getPassword());
        return false;
    }
    
    @Override
    public void add(SysUser user)
    {
        this.checkDuplicate(user);
        user.setRealNamePy(PinyinUtil.cn2py(user.getRealName()));
        // 处理密码
        user.setPassword(this.encrypt(user.getPassword()));
        this.userMapper.insert(user);
    }
    
    @Override
    public void edit(SysUser user)
    {
        this.checkDuplicate(user);
        this.userMapper.updateById(user);
    }
    
    @Override
    public Page<SysUser> search(UserQuery query)
    {
        Page<SysUser> page = query.getPage();
        Wrapper<SysUser> wrapper = new EntityWrapper<SysUser>();
        wrapper.eq("tenant_id", query.getTenantId()).eq("del_flag", false);
        
        if (query.getEnable() != null)
        {
            wrapper.eq("enable", query.getEnable());
        }
        
        if (query.getDeptId() != null && query.getDeptId() > 0)
        {
            List<SysDept> subDepts = this.sysDeptService.findAllSubDept(query.getDeptId());
            
            if (CollectionUtils.isNotEmpty(subDepts))
            {
                List<Long> deptIds = Lists.newArrayList();
                deptIds.add(query.getDeptId());
                for (SysDept subDept : subDepts)
                {
                    deptIds.add(subDept.getId());
                }
                
                wrapper.in("dept_id", deptIds);
            }
            else
            {
                wrapper.eq("dept_id", query.getDeptId());
            }
        }
        query.setKeyword(StringUtils.trimToNull(query.getKeyword()));
        if (StringUtils.isNotBlank(query.getKeyword()))
        {
            wrapper.andNew("id like {0} or real_name like {0} or mobile like {0}", "%" + query.getKeyword() + "%");
        }
        return this.selectPage(page, wrapper);
    }
    
    @Override
    public List<SysUser> findByTenantId(Long tenantId, Boolean enable)
    {
        Wrapper<SysUser> wrapper = new EntityWrapper<SysUser>();
        wrapper.eq("tenant_id", tenantId).eq("del_flag", false);
        if (enable != null)
        {
            wrapper.eq("enable", enable);
        }
        List<SysUser> users = this.selectList(wrapper);
        return users;
    }
    
    @Override
    public void updateByDeptId(SysDept dept)
    {
        Wrapper<SysUser> wrapper = new EntityWrapper<SysUser>();
        wrapper.eq("dept_id", dept.getId());
        List<SysUser> users = this.selectList(wrapper);
        
        for (SysUser user : users)
        {
            user.setDeptName(dept.getName());
            user.setParentDeptIds(dept.getParentIds());
        }
        if (CollectionUtils.isNotEmpty(users))
        {
            this.updateBatchById(users);
        }
    }
    
    @Override
    public List<SysUser> findByDeptId(Long deptId)
    {
        Wrapper<SysUser> wrapper = new EntityWrapper<SysUser>();
        wrapper.eq("dept_id", deptId).eq("del_flag", false);
        return this.selectList(wrapper);
    }
    
    @Override
    public SysUser findByAccount(String account)
    {
        SysUser user = this.findByMobile(account);
        
        if (user == null)
        {
            user = this.findByEmail(account);
            if (user == null)
            {
                throw ExceptionFactory.create("U_009");
            }
        }
        return null;
    }
    
    @Override
    public List<SysUser> findByIds(String ids)
    {
        List<SysUser> list = Lists.newArrayList();
        String[] idss = StringUtils.split(ids, ",");
        
        if (idss.length > 0)
        {
            for (String i : idss)
            {
                SysUser u = this.selectById(i);
                if (u != null)
                {
                    list.add(u);
                }
            }
        }
        return list;
    }
    
}
